package com.qyer.search.sort;

import static com.qyer.log.WarningLogger.logWarning;
import static com.qyer.search.model.lastminute.SKU.unknownPositionSKU;
import static com.qyer.search.utils.ModelUtils.mergeType1;

import com.google.common.collect.Lists;
import com.qyer.commons.mc.MutableCache;
import com.qyer.search.cache.mutable.MutableCaches;
import com.qyer.search.exception.SearchException;
import com.qyer.search.model.SearchParameterEntity;
import com.qyer.search.model.SearchParameterOrigin;
import com.qyer.search.model.SecondComparableTuple2;
import com.qyer.search.model.aggregation.Prefer;
import com.qyer.search.model.lastminute.SKU;
import com.qyer.search.model.lastminute.VSKU;
import com.qyer.search.model.result.Type1SearchEntity;
import com.qyer.search.model.result.Type1SearchPackage;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
 * Created by tangzheng on 16/7/19.
 */
public class VType1Sorter implements SearchSorter{
  private SearchParameterEntity sp;
  private List<Type1SearchEntity> searchEntities;
  private int channel;

  public VType1Sorter(SearchParameterEntity sp, List<Type1SearchEntity> searchEntities, int channel) {
    this.sp = sp;
    this.searchEntities = searchEntities;
    this.channel = channel;
  }

  @Override public List<Type1SearchEntity> sort() throws SearchException {
    if (CollectionUtils.isEmpty(searchEntities)) {
      return Collections.emptyList();
    }
    Map<Integer, Map<Integer, Integer>> dict = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                         .getvStypeMap().get(channel).getSortedMap();

    List<Type1SearchEntity> sortedPackages = new ArrayList<>(searchEntities.size());
    List<VSKU> skus, unknownList;
    int type1, lid;
    Integer position;
    Map<Integer, Integer> positionMap;
    List<SecondComparableTuple2<VSKU, Integer>> tuple2List;
    Type1SearchEntity newPackage;

    for (Type1SearchEntity searchPackage : searchEntities) {
      /*
      * 目前存在小类型, 如1018, 排序字典都当作2667处理的, 这里要把
      * 小类型翻译成2667
      * 但是展示的时候还是分开展示.
      * */
      type1 = searchPackage.getType1();
      positionMap = dict.get(type1);
      if (MapUtils.isEmpty(positionMap)) {
        sortedPackages.add(searchPackage);
        continue;
      }
      skus = searchPackage.getCommonSkus();
      if (CollectionUtils.isEmpty(skus)) {
        continue;
      }
      unknownList = new ArrayList<>(skus.size());
      tuple2List = new ArrayList<>(skus.size());
      for (VSKU sku : skus) {
        lid = sku.getId();
        position = positionMap.get(lid);
        // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
        if (position == null) {
          //logWarning(unknownPositionSKU(lid), sp, null);
          unknownList.add(sku);
        } else {
          tuple2List.add(new SecondComparableTuple2<>(sku, position));
        }
      }
      Collections.sort(tuple2List);
      newPackage = new Type1SearchEntity(type1);
      //营销
      skus = searchPackage.getMarketSkus();
      Collections.sort(skus);
      newPackage.addMarketSkus(skus);

      for (SecondComparableTuple2<VSKU, Integer> tuple2 : tuple2List) {
        newPackage.addSku(tuple2.getFirst());
      }
      // 不认识顺序的商品放到最后
      newPackage.addCommonSkus(unknownList);

      sortedPackages.add(newPackage);
    }
    return sortedPackages;
  }

  public List<Type1SearchEntity> sort(Set<Integer> s1, Set<Integer> s2) throws SearchException {
    long t1 = System.currentTimeMillis();
    if (CollectionUtils.isEmpty(searchEntities)) {
      return Collections.emptyList();
    }
    Map<Integer, Map<Integer, Integer>> dict = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                         .getvStypeMap().get(channel).getSortedMap();

    List<Type1SearchEntity> sortedPackages = new ArrayList<>(searchEntities.size());
    List<VSKU> skus, skus_market, unknownList, unknownListForPrefer;
    List<VSKU> preferSkus, generalSkus;
    int type1, lid;
    Integer position;
    Map<Integer, Integer> positionMap;
    List<SecondComparableTuple2<VSKU, Integer>> tuple2List;
    List<SecondComparableTuple2<VSKU, Integer>> tuple2ListForPrefer;
    Type1SearchEntity newPackage;



    for (Type1SearchEntity searchPackage : searchEntities) {

      type1 = searchPackage.getType1();
      ///////////////////////////////////
      skus = searchPackage.getCommonSkus();
      //System.out.println("type:"+type1+"  size:"+searchPackage.getPackageSize()+";;"+searchPackage.getSkus().size());
      skus_market = searchPackage.getMarketSkus();
      preferSkus = new ArrayList<>(skus.size());
      generalSkus = new ArrayList<>(skus.size());
      //unknownList = new ArrayList<>(skus.size());
      unknownList = Lists.newArrayListWithCapacity(skus.size());
      unknownListForPrefer = new ArrayList<>(skus.size());
      tuple2List = Lists.newArrayListWithCapacity(skus.size());
      tuple2ListForPrefer = Lists.newArrayListWithCapacity(skus.size());
      Collections.sort(skus_market);

      int stype = -1;
      if(CollectionUtils.isNotEmpty(s2)){
        for(int c:s2)
          stype = c;
      }
      /*if(type1 == 150){
        System.out.println("skus size:" + skus.size());
      }*/
      //long t111 = System.currentTimeMillis();

      searchPackage.splitByprefer(s1, stype, preferSkus, generalSkus);
      searchPackage.setPreferSkus(preferSkus);
      searchPackage.setGeneralSkus(generalSkus);
      //long t112 = System.currentTimeMillis();
      //System.out.println("splitByprefer Time:"+(t112-t111));
      /*System.out.println(
        "~~stg:" + type1 + "~~prefer size:" + preferSkus.size() + "~~general size:" + generalSkus
          .size() + "~~common size" + skus.size() + "~~market size:" + skus_market.size() + "~~package size:"+searchPackage.getPackageSize());*/
      ///////////////////////////////////
      positionMap = dict.get(type1);
      if (MapUtils.isEmpty(positionMap)) {
        sortedPackages.add(searchPackage);
        continue;
      }
      if (CollectionUtils.isEmpty(searchPackage.getSkus())) {
        continue;
      }
      /*
      skus = searchPackage.getCommonSkus();
      skus_market = searchPackage.getMarketSkus();
      preferSkus = new ArrayList<>(skus.size());
      generalSkus = new ArrayList<>(skus.size());
      unknownList = new ArrayList<>();
      unknownListForPrefer = new ArrayList<>();
      tuple2List = new ArrayList<>(skus.size());
      tuple2ListForPrefer = new ArrayList<>(skus.size());

      int stype = -1;
      if(CollectionUtils.isNotEmpty(s2)){
        for(int c:s2)
          stype = c;
      }
      if(type1 == 150){
        System.out.println("skus size:" + skus.size());
      }
      searchPackage.splitByprefer(s1, stype, preferSkus, generalSkus);
      */
      newPackage = new Type1SearchEntity(type1);
      //营销//////////////////////////////////
      newPackage.addMarketSkus(skus_market);
      /////////////////////////////////////////////////////////////////////////////////////////
      if(CollectionUtils.isNotEmpty(preferSkus)) {
        for (VSKU sku : preferSkus) {
          lid = sku.getId();
          position = positionMap.get(lid);
          // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
          if (position == null) {
            //logWarning(unknownPositionSKU(lid), sp, null);
            unknownListForPrefer.add(sku);
          } else {
            tuple2ListForPrefer.add(new SecondComparableTuple2<>(sku, position));
          }
        }
        Collections.sort(tuple2ListForPrefer);
        for (SecondComparableTuple2<VSKU, Integer> tuple2 : tuple2ListForPrefer) {
          newPackage.addSku(tuple2.getFirst());
          newPackage.addPrefer(tuple2.getFirst());
        }
        //System.out.println("1sort:"+(t212-t211));
        //System.out.println("fsort:"+(t213-t212));
        // 不认识顺序的商品放到最后
        newPackage.addCommonSkus(unknownListForPrefer);
        newPackage.addPrefer(unknownListForPrefer);
      }

      //System.out.println("1~~stg:" + type1 +"~~prefer size:"+newPackage.getPreferSkus().size()+"~~general size:"+newPackage.getGeneralSkus().size() + "~~common size" + newPackage.getCommonSkus().size() +"~~market size:"+newPackage.getMarketSkus().size() + "~~~package szie:"+newPackage.getPackageSize());
      /////////////////////////////////////////////////////////////////////////////////////////
      long t21 = System.currentTimeMillis();
      /////////////////////////////////////////////////////////////////////////////////////////
      if(CollectionUtils.isNotEmpty(generalSkus)) {
        for (VSKU sku : generalSkus) {
          lid = sku.getId();
          position = positionMap.get(lid);
          // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
          if (position == null) {
            //logWarning(unknownPositionSKU(lid), sp, null);
            unknownList.add(sku);
          } else {
            //long tupleTime1 = System.currentTimeMillis();
            tuple2List.add(new SecondComparableTuple2<>(sku, position));
            //System.out.println("SecondComparableTuple2:"+(System.currentTimeMillis() - tupleTime1));
          }
        }
        //long t22 = System.currentTimeMillis();
        Collections.sort(tuple2List);
        //long t23 = System.currentTimeMillis();
        for (SecondComparableTuple2<VSKU, Integer> tuple2 : tuple2List) {
          newPackage.addSku(tuple2.getFirst());
          newPackage.addGeneral(tuple2.getFirst());
        }
        //long t24 = System.currentTimeMillis();
        //System.out.println("a:"+(t22-t21));
        //System.out.println("b:"+(t23-t22));
        //System.out.println("c:"+(t24-t23));
        // 不认识顺序的商品放到最后
        newPackage.addCommonSkus(unknownList);
        newPackage.addGeneral(unknownList);
      }
      //System.out.println("2~~stg:" + type1 +"~~prefer size:"+newPackage.getPreferSkus().size()+"~~general size:"+newPackage.getGeneralSkus().size() + "~~common size" + newPackage.getCommonSkus().size() +"~~market size:"+newPackage.getMarketSkus().size() + "~~~package szie:"+newPackage.getPackageSize());
      sortedPackages.add(newPackage);
    }
    //System.out.println("默认排序time:"+(System.currentTimeMillis() - t1));
    return sortedPackages;
  }


  public List<Type1SearchEntity> sortWithoutMarket(Set<Integer> s1, Set<Integer> s2) throws SearchException {
    long t1 = System.currentTimeMillis();
    if (CollectionUtils.isEmpty(searchEntities)) {
      return Collections.emptyList();
    }
    Map<Integer, Map<Integer, Integer>> dict = MutableCaches.getInstance().Z_TAG_SNAPSHOT.getCacheContent()
                                                                                         .getvStypeMap().get(channel).getSortedMap();

    List<Type1SearchEntity> sortedPackages = new ArrayList<>(searchEntities.size());
    List<VSKU> skus, unknownList, unknownListForPrefer, skus_switch;
    List<VSKU> preferSkus, generalSkus;
    int type1, lid;
    Integer position;
    Map<Integer, Integer> positionMap;
    List<SecondComparableTuple2<VSKU, Integer>> tuple2List;
    List<SecondComparableTuple2<VSKU, Integer>> tuple2ListForPrefer;
    Type1SearchEntity newPackage;



    for (Type1SearchEntity searchPackage : searchEntities) {

      type1 = searchPackage.getType1();
      ///////////////////////////////////
      skus = searchPackage.getSkus();
      //System.out.println("type:"+type1+"  size:"+skus.size());
      //skus_market = searchPackage.getMarketSkus();
      preferSkus = new ArrayList<>(skus.size());
      generalSkus = new ArrayList<>(skus.size());
      unknownList = new ArrayList<>(skus.size());
      unknownListForPrefer = new ArrayList<>(skus.size());
      tuple2List = Lists.newArrayListWithCapacity(skus.size());
      tuple2ListForPrefer = Lists.newArrayListWithCapacity(skus.size());
      //Collections.sort(skus_market);

      int stype = -1;
      if(CollectionUtils.isNotEmpty(s2)){
        for(int c:s2)
          stype = c;
      }
      /*if(type1 == 150){
        System.out.println("skus size:" + skus.size());
      }*/
      searchPackage.splitBypreferAll(s1, stype, preferSkus, generalSkus);
      searchPackage.setPreferSkus(preferSkus);
      searchPackage.setGeneralSkus(generalSkus);
      /*System.out.println(
        "~~stg:" + type1 + "~~prefer size:" + preferSkus.size() + "~~general size:" + generalSkus
          .size() + "~~common size" + skus.size() + "~~market size:" + skus_market.size() + "~~package size:"+searchPackage.getPackageSize());*/
      ///////////////////////////////////
      positionMap = dict.get(type1);
      if (MapUtils.isEmpty(positionMap)) {
        sortedPackages.add(searchPackage);
        continue;
      }
      if (CollectionUtils.isEmpty(searchPackage.getSkus())) {
        continue;
      }

      newPackage = new Type1SearchEntity(type1);
      //营销//////////////////////////////////
      //newPackage.addMarketSkus(skus_market);
      /////////////////////////////////////////////////////////////////////////////////////////
      if(CollectionUtils.isNotEmpty(preferSkus)) {
        for (VSKU sku : preferSkus) {
          lid = sku.getId();
          position = positionMap.get(lid);
          // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
          if (position == null) {
            //logWarning(unknownPositionSKU(lid), sp, null);
            unknownListForPrefer.add(sku);
          } else {
            tuple2ListForPrefer.add(new SecondComparableTuple2<>(sku, position));
          }
        }
        Collections.sort(tuple2ListForPrefer);
        for (SecondComparableTuple2<VSKU, Integer> tuple2 : tuple2ListForPrefer) {
          newPackage.addSku(tuple2.getFirst());
          newPackage.addPrefer(tuple2.getFirst());
        }
        // 不认识顺序的商品放到最后
        newPackage.addCommonSkus(unknownListForPrefer);
        newPackage.addPrefer(unknownListForPrefer);
      }

      //System.out.println("1~~stg:" + type1 +"~~prefer size:"+newPackage.getPreferSkus().size()+"~~general size:"+newPackage.getGeneralSkus().size() + "~~common size" + newPackage.getCommonSkus().size() +"~~market size:"+newPackage.getMarketSkus().size() + "~~~package szie:"+newPackage.getPackageSize());

      /////////////////////////////////////////////////////////////////////////////////////////
      if(CollectionUtils.isNotEmpty(generalSkus)) {
        for (VSKU sku : generalSkus) {
          lid = sku.getId();
          position = positionMap.get(lid);
          // 获取位置信息, 放到SecondComparableTuple2准备按二元组的第二元素排序, 不认识的商品不参与排序
          if (position == null) {
            //logWarning(unknownPositionSKU(lid), sp, null);
            unknownList.add(sku);
          } else {
            tuple2List.add(new SecondComparableTuple2<>(sku, position));
          }
        }
        Collections.sort(tuple2List);
        for (SecondComparableTuple2<VSKU, Integer> tuple2 : tuple2List) {
          newPackage.addSku(tuple2.getFirst());
          newPackage.addGeneral(tuple2.getFirst());
        }
        // 不认识顺序的商品放到最后
        newPackage.addCommonSkus(unknownList);
        newPackage.addGeneral(unknownList);
      }
      //System.out.println("2~~stg:" + type1 +"~~prefer size:"+newPackage.getPreferSkus().size()+"~~general size:"+newPackage.getGeneralSkus().size() + "~~common size" + newPackage.getCommonSkus().size() +"~~market size:"+newPackage.getMarketSkus().size() + "~~~package szie:"+newPackage.getPackageSize());


      sortedPackages.add(newPackage);
    }
    //System.out.println("混排time:"+(System.currentTimeMillis() - t1));
    return sortedPackages;
  }
}
